package org.streets.eis.component.combobox;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.wicket.Response;
import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteSettings;
import org.apache.wicket.markup.html.IHeaderResponse;
import org.apache.wicket.markup.html.tree.BaseTree;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.string.Strings;

import org.streets.eis.component.WebResources;
import org.streets.eis.component.model.DataModel;
import org.streets.eis.component.model.ListItem;

/**
 * 分级生成DataModel时，取某一节点A的子节点列表时，应根据每个子节点是否还有下级子节点决定是否在该子节点下加一个DUMMY
 * 渲染时，如果子节点下有Dummy，会渲染成非叶子节点，否则渲染成叶子节点
 * 
 * 注意：html form的reset动作对此控件无效
 */
public abstract class TreeComboBox extends ComboBox<DataModel<ListItem>>{
	private static final long serialVersionUID = 1L;

	private boolean onlySelectLeaf = true; 
	
	public static final 	DataModel<ListItem> DUMMY = new DataModel<ListItem>();
	
	protected Map<String,DataModel<ListItem>> idModels = new HashMap<String,DataModel<ListItem>>();
	
	public TreeComboBox(String id, IModel<ListItem> model,DataModel<ListItem> dataModel){
		this(id,model,dataModel,true);
	}
	
	public TreeComboBox(String id, IModel<ListItem> model,DataModel<ListItem> dataModel,boolean canInput){
		super(id,model,dataModel,canInput);
	}
	
	public TreeComboBox(String id, IModel<ListItem> model,DataModel<ListItem> dataModel,boolean canInput, AutoCompleteSettings settings){
		super(id, model,dataModel,canInput,settings);
	}
	
	public TreeComboBox(String id,DataModel<ListItem> dataModel){
		this(id,dataModel,true);
	}
	
	public TreeComboBox(String id,DataModel<ListItem> dataModel,boolean canInput){
		super(id,dataModel,canInput);
	}
	
	public TreeComboBox(String id,DataModel<ListItem> dataModel,boolean canInput, AutoCompleteSettings settings){
		super(id, dataModel,canInput,settings);
	}
	
	public boolean getOnlySelectLeaf(){
		return onlySelectLeaf;
	}
	
	public TreeComboBox setOnlySelectLeaf(boolean onlySelectLeaf){
		this.onlySelectLeaf = onlySelectLeaf;
		return this;
	}
	
	public void renderHead(IHeaderResponse response) {
		response.renderCSSReference(WebResources.Streets.ComboBox.TREE_CSS);
		response.renderJavascriptReference(WebResources.Streets.ComboBox.TREE_JS);		
	}
	
	protected DataModel<ListItem> getChildrenDataModel(String parentId){
		DataModel<ListItem> model = idModels.get(parentId);
		if (model==null){
			throw new RuntimeException("Unable to find DataModel<ListItem> of Node : id = " + parentId);
		}
		if (model.getChildrenCount()==0 || model.getChild(0).getObject()==null){
			model.getChildren().clear();
			model.getChildren().addAll(generateChildrenDataModel(parentId));
		}
		return model;
	}
	
	protected void renderDataModel(DataModel<ListItem> model,Response response){
		response.write("<UL class=\"tree\">");
		if (model==getDataModel() && !isRequired()){
			renderTreeNode(new DataModel<ListItem>(ListItem.empty()),response);
		}
		if (model!=null){
			for (Iterator<DataModel<ListItem>> iter = model.getChildren().iterator(); iter.hasNext();) {
				DataModel<ListItem> m = iter.next();
				if (m!=null){
					renderTreeNode(m,response);
					idModels.put(m.getObject().getId(), m);
				}
			}
		}
		response.write("</UL>");
	}
	
	protected void renderTreeNode(DataModel<ListItem> model,Response response){
		ListItem item = model.getObject();
		String textValue = item.getText();
		if (textValue==null||textValue.trim().length()==0) textValue = "&nbsp;";
		textValue = textValue.trim();
		String id = item.getId();	

        boolean hasChild = model.getChildrenCount()>0;
        if (hasChild&&Strings.isEmpty(getItemIcon(item,false))){
        	item.setIcon(BaseTree.class.getName()+"/res/folder-closed.gif");
        }
		
        response.write("<li><div  i=\""+id+"\" >");

        String className = hasChild ? "closed" : "item";        
        response.write("<a class=\""+className+"\" />");
        
        response.write("<a style=\"width:16px;height:16px;vertical-align:middle;background: url(");
		response.write(getItemIcon(item,true));
		response.write(") left center no-repeat\" />");

		response.write("<a>");
		response.write(textValue);
		response.write("</a></div>");
		
		if (hasChild){
			response.write("<DIV class=\"children\"/>");
		}
		response.write("</li>");
	}
	
	@Override
	protected void onIconClicked(Response response){
		String parentId = getRequest().getParameter("p");
		if (parentId!=null&&parentId.length()>0){
			renderDataModel(getChildrenDataModel(parentId),response);
		}else{
			renderDataModel(getDataModel(),response);
		}		
	}
	
	@Override
	protected String getInitJavascript(CharSequence callbackUrl,String SettingsJS, String indicatorId){
		final String id = getMarkupId();
		return String.format("var %s = new Streets.TreeComboBox('%s','%s',%s,%s,%s);", id,id,
				callbackUrl, SettingsJS, indicatorId,onlySelectLeaf);
	}
		
	protected abstract List<DataModel<ListItem>> generateChildrenDataModel(String parentId);
	
}
